﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using MPI;

namespace DwarfConfigurator
{
    class BuilderMpi : IBuilder
    {
        /// <summary>
        /// The settings for this dwarf.
        /// </summary>
        private Settings settings;

        private DataModel model;

        public Settings getSetting()
        {
            return settings;
        }

        public DataModel getModel()
        {
            return model;
        }


        /// <summary>
        /// Get settings from the command line.
        /// </summary>
        /// <param name="args">
        /// Cli params.
        /// </param>
        /// <param name="solver">
        /// Instance of Solver.
        /// </param>
        public void buildSettings(String[] args, DataModel model)
        {
            bool error = false;
            if (model.isRootThread)
            {
                try
                {
                    settings = new Settings();
                    settings.Init(args, model);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    error = true;
                }
            }
            //Distribute error if that occurred while parsing.
            Communicator.world.Broadcast(ref error, DataModel.ROOT_PROCESS);
            if (error) throw new Exception("");
            //Distribute the length of matrix for each process.
            Communicator.world.Broadcast(ref model.length, DataModel.ROOT_PROCESS);
        }

        public DataModel process(String[] args)
        {
            try
            {

                if (Communicator.world.Size == 1)
                {
                    throw new Exception("Only one mpi process.");
                }

                model = new DataModel();
                if (Communicator.world.Rank == DataModel.ROOT_PROCESS)
                {
                    model.isRootThread = true;
                }

                buildSettings(args, model);                               // Get settings from the command line.

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                usage();
            }

            return model;
        }

        /// <summary>
        /// Write the rules of command line structure.
        /// </summary>
        [DllImport(@"CliTools.dll")]
        private static extern void usage();
    }
}
